<template>
	<div>
		<a-row :gutter="[16, 0]">
			<a-col span="4" style="padding: 0px 12px;">
				<a-collapse accordion v-model="collapseActiveKey">
					<a-collapse-panel key="1" header="普通控件">
						<a-list item-layout="horizontal" :split="false"
							:data-source="widget.filter(item => item.type < 50)">
							<a-list-item slot="renderItem" slot-scope="item" @click="onWidgetClick(item)">
								<div style="padding: 0px 12px;">
									<a-avatar :size="36" shape="square" :src="getWidgetIcon(item)"
										style="margin-right: 12px;" />
									<span>{{item.name}}</span>
								</div>
							</a-list-item>
						</a-list>
					</a-collapse-panel>
					<a-collapse-panel key="2" header="高级控件">
						<a-list item-layout="horizontal" :split="false"
							:data-source="widget.filter(item => item.type >= 50)">
							<a-list-item slot="renderItem" slot-scope="item" @click="onWidgetClick(item)">
								<div style="padding: 0px 12px;">
									<a-avatar :size="36" shape="square" :src="getWidgetIcon(item)"
										style="margin-right: 12px;" />
									<span>{{item.name}}</span>
								</div>
							</a-list-item>
						</a-list>
					</a-collapse-panel>
				</a-collapse>
			</a-col>
			<a-col class="canvas-context" span="15" style="padding: 0;">
				<div class="canvas-box" ref="canvasBox" @click.stop="cancelActiveObject">
					<div class="canvas-content">
						<canvas id="canvas" class="canvas" />
					</div>
				</div>
				<contextmenu ref="rightMenu" :itemList="rightMenuItemList" :visible.sync="showRightMenu"
					@select="onRightMenuSelect" style="user-select: none;" />
			</a-col>
			<a-col span="5">
				<a-form-model class="widget-card" :model="form" ref="form" :rules="validatorRules"
					:label-col="{span: 7}" :wrapperCol="{span: 15, offset: 1}">
					<a-card>
						<span slot="title">
							<a-icon class="margin-right-8" type="setting" />模版信息
						</span>
						<a-form-model-item label="所属机构" prop="organizationId">
							<a-tree-select show-search :filterTreeNode="filterTreeNode" v-model="form.organizationId"
								style="width: 100%;" :dropdown-style="{ maxHeight: '300px', overflow: 'auto' }"
								:tree-data="organizationTreeData" :tree-default-expand-all="true"
								:getPopupContainer="(triggerNode)=>{ return triggerNode.parentNode}">
								<template slot="title" slot-scope="item">
									<span v-if="item.type == 0">
										<a-icon type="bank" /> {{item.customTitle}}
									</span>
									<span v-else-if="item.type == 1">
										<a-icon type="shop" /> {{item.customTitle}}
									</span>
									<span v-else-if="item.type == 2">
										<a-icon type="apartment" /> {{item.customTitle}}
									</span>
									<span v-else>
										<a-icon type="question-circle" /> {{item.customTitle}}
									</span>
								</template>
							</a-tree-select>
						</a-form-model-item>
						<a-form-model-item label="模版类型" prop="type">
							<a-select v-model="form.type"
								:getPopupContainer="(triggerNode)=>{ return triggerNode.parentNode}">
								<a-select-option v-for="item in dict.type" :key="item.key" :value="item.value">
									{{item.title}}
								</a-select-option>
							</a-select>
						</a-form-model-item>
						<a-form-model-item label="模版名称" prop="name">
							<a-input allowClear v-model="form.name" />
						</a-form-model-item>
						<a-form-model-item label="备注" prop="remarks">
							<a-input allowClear v-model="form.remarks" />
						</a-form-model-item>
					</a-card>
					<a-card style="margin-top: 12px;">
						<span slot="title">
							<a-icon class="margin-right-8" type="setting" />模版尺寸
						</span>
						<a-form-model-item prop="canvasZoom">
							<span slot="label">缩放({{this.canvasZoom}}%)</span>
							<a-slider v-model="canvasZoom" :min="1" :max="200" :marks="canvasZoomMask"
								:default-value="100" :tip-formatter="value => `${value}%`" />
						</a-form-model-item>
						<a-form-model-item label="宽度(px)" prop="canvasWidth" required>
							<a-input-number :min="100" :max="3000" v-model="form.canvasWidth"
								:parser="value => value.replace('.', '')" style="width: 100%;" />
						</a-form-model-item>
						<a-form-model-item label="高度(px)" prop="canvasHeight" required>
							<a-input-number :min="100" :max="3000" v-model="form.canvasHeight"
								:parser="value => value.replace('.', '')" style="width: 100%;" />
						</a-form-model-item>
					</a-card>
					<a-card style="margin-top: 12px;">
						<span slot="title">
							<a-icon class="margin-right-8" type="setting" />控件信息
						</span>
						<a-form-model-item label="控件序号" prop="widget.index">
							<a-input-number disabled :min="0" v-model="form.widget.index" style="width: 100%;" />
						</a-form-model-item>
						<a-form-model-item label="控件名称" prop="widget.name">
							<a-input allowClear :disabled="!canvas || !canvas.getActiveObject()"
								v-model="form.widget.name" @change="onWidgetNameChange" />
						</a-form-model-item>
						<a-form-model-item label="控件层级" prop="widget.zIndex">
							<a-input-number disabled :min="0" v-model="form.widget.zIndex" style="width: 100%;" />
						</a-form-model-item>
					</a-card>
					<a-card style="margin-top: 12px;">
						<span slot="title">
							<a-icon class="margin-right-8" type="setting" />控件布局
						</span>
						<a-row>
							<a-col span="11">
								<a-form-model-item label="X" :label-col="{span: 10}" :wrapper-col="{span: 14}"
									prop="widget.x">
									<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()" :min="0"
										v-model="form.widget.x" :parser="value => value.replace('.', '')"
										@change="onWidgetXChange" />
								</a-form-model-item>
							</a-col>
							<a-col span="11" offset="1">
								<a-form-model-item label="X(%)" :label-col="{span: 10}" :wrapper-col="{span: 14}"
									prop="widget.percentX">
									<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()" :min="0"
										:max="100" v-model="form.widget.percentX" @change="onWidgetPercentXChange" />
								</a-form-model-item>
							</a-col>
						</a-row>
						<a-row>
							<a-col span="11">
								<a-form-model-item label="Y" :label-col="{span: 10}" :wrapper-col="{span: 14}"
									prop="widget.y">
									<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()" :min="0"
										v-model="form.widget.y" :parser="value => value.replace('.', '')"
										@change="onWidgetYChange" />
								</a-form-model-item>
							</a-col>
							<a-col span="11" offset="1">
								<a-form-model-item label="Y(%)" :label-col="{span: 10}" :wrapper-col="{span: 14}"
									prop="widget.percentY">
									<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()" :min="0"
										:max="100" v-model="form.widget.percentY" @change="onWidgetPercentYChange" />
								</a-form-model-item>
							</a-col>
						</a-row>
						<a-row>
							<a-col span="11">
								<a-form-model-item label="宽(px)" :label-col="{span: 10}" :wrapper-col="{span: 14}"
									prop="widget.width">
									<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()" :min="0"
										v-model="form.widget.width" :parser="value => value.replace('.', '')"
										@change="onWidgetWidthChange" />
								</a-form-model-item>
							</a-col>
							<a-col span="11" offset="1">
								<a-form-model-item label="宽(%)" :label-col="{span: 10}" :wrapper-col="{span: 14}"
									prop="widget.percentWidth">
									<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()" :min="0"
										:max="100" v-model="form.widget.percentWidth"
										@change="onWidgetPercentWidthChange" />
								</a-form-model-item>
							</a-col>
						</a-row>
						<a-row>
							<a-col span="11">
								<a-form-model-item label="高(px)" :label-col="{span: 10}" :wrapper-col="{span: 14}"
									prop="widget.height">
									<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()" :min="0"
										v-model="form.widget.height" :parser="value => value.replace('.', '')"
										@change="onWidgetHeightChange" />
								</a-form-model-item>
							</a-col>
							<a-col span="11" offset="1">
								<a-form-model-item label="高(%)" :label-col="{span: 10}" :wrapper-col="{span: 14}"
									prop="widget.percentHeight">
									<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()" :min="0"
										:max="100" v-model="form.widget.percentHeight"
										@change="onWidgetPercentHeightChange" />
								</a-form-model-item>
							</a-col>
						</a-row>
					</a-card>
					<a-card style="margin-top: 12px;" v-if="showWidgetStylePanel">
						<span slot="title">
							<a-icon class="margin-right-8" type="setting" />控件样式
						</span>
						<a-form-model-item label="字体大小" v-if="showTextStylePanel">
							<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()"
								v-model="form.widget.fontSize" :min="1" :max="1000" :formatter="value => `${value}px`"
								:parser="value => value.replace('.', '').replace('px', '')" style="width: 100%;"
								@change="onWidgetFontSizeChange" />
						</a-form-model-item>
						<a-form-model-item label="字体颜色" v-if="showTextStylePanel">
							<a-input-group>
								<a-row type="flex" justify="space-between" align="middle">
									<a-col :span="4">
										<colorPicker :disabled="!canvas || !canvas.getActiveObject()"
											v-model="form.widget.fontColor"
											@change="onColorPickerWidgetFontColorChange" />
									</a-col>
									<a-col :span="19">
										<a-input allowClear :disabled="!canvas || !canvas.getActiveObject()"
											v-model="form.widget.fontColor" :formatter="value => `#${value}`"
											@change="onWidgetFontColorChange" />
									</a-col>
								</a-row>
							</a-input-group>
						</a-form-model-item>
						<a-form-model-item label="背景颜色" v-if="showBackgroundStylePanel">
							<a-input-group>
								<a-row type="flex" justify="space-between" align="middle">
									<a-col :span="4">
										<colorPicker :disabled="!canvas || !canvas.getActiveObject()"
											v-model="form.widget.backgroundColor"
											@change="onColorPickerWidgetBackgroundColorChange" />
									</a-col>
									<a-col :span="19">
										<a-input allowClear :disabled="!canvas || !canvas.getActiveObject()"
											v-model="form.widget.backgroundColor" :formatter="value => `#${value}`"
											@change="onWidgetBackgroundColorChange" />
									</a-col>
								</a-row>
							</a-input-group>
						</a-form-model-item>
					</a-card>
					<a-card style="margin-top: 12px;" v-if="showTextSpeedPanel">
						<span slot="title">
							<a-icon class="margin-right-8" type="setting" />其它设置
						</span>
						<a-form-model-item label="字幕速度">
							<a-input-number allowClear :disabled="!canvas || !canvas.getActiveObject()"
								v-model="form.widget.textSpeed" :min="0" :max="20"
								:parser="value => value.replace('.', '')" style="width: 100%;"
								@change="onWidgetTextSpeedChange" />
						</a-form-model-item>
					</a-card>
					<a-card style="margin-top: 12px;" v-if="showVideoImagePanel">
						<span slot="title">
							<a-icon class="margin-right-8" type="setting" />控件属性
						</span>
						<a-form-model-item label="子类型">
							<a-input disabled v-model="form.widget.childrenType" />
						</a-form-model-item>
					</a-card>
				</a-form-model>
			</a-col>
		</a-row>
	</div>
</template>

<script>
	import Contextmenu from '@/components/menu/context-menu'
	import {
		fabric
	} from 'fabric'
	import {
		base64ToFile
	} from '@/utils/util'
	import cloneDeep from 'lodash.clonedeep'

	export default {
		name: 'TemplateEditor',
		components: {
			Contextmenu
		},
		props: {
			defaultFontColor: {
				type: String,
				default: '#000000'
			},
			defaultBackgroundColor: {
				type: String,
				default: '#e3e3e3'
			},
			defaultFontSize: {
				type: Number,
				default: 30
			},
			defaultTextSpeed: {
				type: Number,
				default: 3
			}
		},
		data() {
			return {
				collapseActiveKey: 1,
				widget: [{
						type: 0,
						multiple: true,
						typeString: 'Background',
						name: '背景',
						icon: require('../../assets/widget/widget-bg.png'),
						disableIcon: require('../../assets/widget/widget-bg-disabled.png')
					},
					{
						type: 1,
						multiple: true,
						typeString: 'Logo',
						name: 'LOGO',
						icon: require('../../assets/widget/widget-logo.png'),
						disableIcon: require('../../assets/widget/widget-logo-disabled.png')
					},
					{
						type: 2,
						multiple: true,
						typeString: 'Image',
						name: '图片',
						icon: require('../../assets/widget/widget-image.png'),
						disableIcon: require('../../assets/widget/widget-image-disabled.png')
					},
					{
						type: 3,
						multiple: true,
						typeString: 'Video',
						name: '视频',
						icon: require('../../assets/widget/widget-bg.png'),
						disableIcon: require('../../assets/widget/widget-video-disabled.png')
					},
					{
						type: 4,
						multiple: true,
						typeString: 'Text',
						name: '字幕',
						icon: require('../../assets/widget/widget-text.png'),
						disableIcon: require('../../assets/widget/widget-text-disabled.png')
					},
					{
						type: 5,
						multiple: false,
						typeString: 'Dtmb',
						name: 'DTMB',
						icon: require('../../assets/widget/widget-dtmb.png'),
						disableIcon: require('../../assets/widget/widget-dtmb-disabled.png')
					},
					{
						type: 6,
						multiple: false,
						typeString: 'LiveSource',
						name: '流媒体',
						icon: require('../../assets/widget/widget-live-source.png'),
						disableIcon: require('../../assets/widget/widget-live-source-disabled.png')
					},
					{
						type: 50,
						multiple: false,
						typeString: 'Weather',
						name: '天气',
						icon: require('../../assets/widget/widget-weather.png'),
						disableIcon: require('../../assets/widget/widget-weather-disabled.png')
					},
					{
						type: 51,
						multiple: false,
						typeString: 'Date',
						name: '日期',
						icon: require('../../assets/widget/widget-date.png'),
						disableIcon: require('../../assets/widget/widget-date-disabled.png')
					},
					{
						type: 52,
						multiple: false,
						typeString: 'Time',
						name: '时间',
						icon: require('../../assets/widget/widget-time.png'),
						disableIcon: require('../../assets/widget/widget-time-disabled.png')
					},
					{
						type: 53,
						multiple: false,
						typeString: 'Website',
						name: '网页',
						icon: require('../../assets/widget/widget-website.png'),
						disableIcon: require('../../assets/widget/widget-website-disabled.png')
					},
					{
						type: 54,
						multiple: false,
						typeString: 'List',
						name: '站点列表',
						icon: require('../../assets/widget/widget-list.png'),
						disableIcon: require('../../assets/widget/widget-list-disabled.png')
					},
					{
						type: 55,
						multiple: true,
						typeString: 'VideoImage',
						name: '联动视频图片',
						icon: require('../../assets/widget/widget-video-image.png'),
						disableIcon: require('../../assets/widget/widget-video-image-disabled.png')
					}
				],
				organizationTreeData: [],
				showRightMenu: false,
				showWidgetStylePanel: false,
				showBackgroundStylePanel: false,
				showTextStylePanel: false,
				showTextSpeedPanel: false,
				showVideoImagePanel: false,
				form: {
					organizationId: undefined,
					name: undefined,
					type: undefined,
					remarks: undefined,
					canvasWidth: 1920,
					canvasHeight: 1080,
					widget: {
						name: undefined,
						index: undefined,
						zIndex: undefined,
						x: undefined,
						y: undefined,
						percentX: undefined,
						percentY: undefined,
						width: undefined,
						height: undefined,
						percentWidth: undefined,
						percentHeight: undefined,
						fontSize: this.defaultFontSize,
						fontColor: this.defaultFontColor,
						backgroundColor: this.defaultBackgroundColor,
						textSpeed: this.defaultTextSpeed,
						childrenType: undefined
					},
					url: undefined
				},
				validatorRules: {
					organizationId: [{
						required: true,
						message: '请选择组织机构',
						trigger: 'change'
					}],
					type: [{
						required: true,
						message: '请选择模版类型',
						trigger: 'change'
					}],
					name: [{
						required: true,
						message: '请输入模版名称',
						trigger: 'blur'
					}],
					canvasWidth: [{
						required: true,
						message: '请输入画布宽度',
						trigger: 'change'
					}],
					canvasHeight: [{
						required: true,
						message: '请输入画布高度',
						trigger: 'change'
					}]
				},
				fabric: undefined,
				fabricOptions: {
					backgroundColor: 'rgba(255, 255, 255, 1.0)',
					isDrawingMode: false,
					selection: false,
					selectable: false,
					devicePixelRatio: true,
					altActionKey: 'none',
					uniScaleKey: 'ctrlKey',
					stateful: true,
					fireRightClick: true,
					stopContextMenu: true,
					preserveObjectStacking: true,
					uniformScaling: false
				},
				canvas: undefined,
				canvasContent: undefined,

				canvasZoom: 100,
				canvasZoomMask: {
					0: '0%',
					100: '100%',
					200: '200%'
				},
				zoomOffset: 200,
				widgetData: {
					Background: [],
					Logo: [],
					Image: [],
					Video: [],
					Text: [],
					Dtmb: [],
					LiveSource: [],
					Weather: [],
					Date: [],
					Time: [],
					Website: [],
					List: [],
					VideoImage: []
				},
				file: undefined,
				dict: {
					type: []
				}
			}
		},
		computed: {
			rightMenuItemList() {
				return [{
						key: '1',
						icon: 'vertical-align-top',
						text: '置顶'
					},
					{
						key: '2',
						icon: 'arrow-up',
						text: '上移'
					},
					{
						key: '3',
						icon: 'arrow-down',
						text: '下移'
					},
					{
						key: '4',
						icon: 'vertical-align-bottom',
						text: '置底'
					},
					{
						key: '5',
						icon: 'delete',
						text: '删除'
					}
				]
			}
		},
		watch: {
			'form.canvasWidth'(val) {
				this.canvas.setWidth(val)
			},
			'form.canvasHeight'(val) {
				this.canvas.setHeight(val)
			},
			canvasZoom(val) {
				let realZoom = val / this.zoomOffset
				this.canvasContent.style.transform = 'scale(' + realZoom + ', ' + realZoom + ')'
			}
		},
		methods: {
			filterTreeNode(input, treeNode) {
				return treeNode.data.props.customTitle.includes(input)
			},
			clearFormData() {
				this.form.widget = {
					name: undefined,
					index: undefined,
					zIndex: undefined,
					x: undefined,
					y: undefined,
					percentX: undefined,
					percentY: undefined,
					width: undefined,
					height: undefined,
					percentWidth: undefined,
					percentHeight: undefined,
					fontSize: undefined,
					fontColor: this.defaultFontColor,
					backgroundColor: this.defaultBackgroundColor,
					textSpeed: undefined
				}
				this.showWidgetStylePanel = false
				this.showBackgroundStylePanel = false
				this.showTextStylePanel = false
				this.showTextSpeedPanel = false
				this.showVideoImagePanel = false
			},
			onRightMenuSelect(key) {
				var obj = this.canvas.getActiveObject()
				if (obj) {
					switch (key) {
						// 置顶
						case '1':
							this.canvas.bringToFront(obj)
							break
							// 上移
						case '2':
							this.canvas.bringForward(obj)
							break
							// 下移
						case '3':
							this.canvas.sendBackwards(obj)
							break
							// 置底
						case '4':
							this.canvas.sendToBack(obj)
							break
							// 删除
						case '5':
							// 联动视频图片关联删除
							if (obj.formData.type == 55) {
								let index = obj.formData.index
								this.canvas.remove(obj)
								this.canvas.getObjects().forEach(item => {
									if (item.formData.type == 55 && item.formData.index == index) {
										this.canvas.remove(item)
									}
								})
							}
							// 普通删除
							else {
								this.canvas.remove(obj)
							}
							this.widgetData[obj.formData.typeString] = []
							break
						default:
							break
					}
					this.canvas.getObjects().forEach((item, index) => item.formData.zIndex = index)
					this.form.widget.zIndex = obj.formData.zIndex
					this.canvas.renderAll()
				}
			},
			getWidgetIcon(item) {
				if (!item.multiple && this.widgetData[item.typeString].length > 0) {
					return item.disableIcon
				} else {
					return item.icon
				}
			},
			initCanvas() {
				this.canvasContent = document.getElementsByClassName('canvas-content')[0]
				this.canvas = new fabric.Canvas('canvas', this.fabricOptions)
				fabric.Object.prototype.transparentCorners = false
				fabric.Object.prototype.cornerColor = 'rgba(48, 130, 217, 0.75)'
				fabric.Object.prototype.cornerStyle = 'square'
				fabric.Object.prototype.cornerSize = 20
				this.resizeCanvas()
				this.initCanvasEvent()
			},
			resizeCanvas() {
				this.canvas.setWidth(this.form.canvasWidth)
				this.canvas.setHeight(this.form.canvasHeight)
				let realZoom = this.canvasZoom / this.zoomOffset
				this.canvasContent.style.transform = 'scale(' + realZoom + ', ' + realZoom + ')'
			},
			initCanvasEvent() {
				// 移动事件
				this.canvas.on('object:moving', (e) => {
					var obj = e.target
					obj.setCoords()
					var boundingRect = obj.getBoundingRect()
					var left = parseInt(boundingRect.left)
					var top = parseInt(boundingRect.top)
					var width = parseInt(boundingRect.width)
					var height = parseInt(boundingRect.height)
					// 限制移动范围
					if (top < 0 || left < 0) {
						obj.top = Math.max(obj.top, obj.top - top)
						obj.left = Math.max(obj.left, obj.left - left)
						obj.setCoords()
					}
					// 限制移动范围
					if (top + height > this.canvas.height || left + width > this.canvas.width) {
						obj.top = Math.min(obj.top, this.canvas.height - height + obj.top - top)
						obj.left = Math.min(obj.left, this.canvas.width - width + obj.left - left)
						obj.setCoords()
					}
					// 异步更新数据
					setTimeout(() => {
						this.form.widget.x = parseInt(obj.left)
						this.form.widget.y = parseInt(obj.top)
						this.form.widget.percentX = (obj.left / this.canvas.width * 100).toFixed(2)
						this.form.widget.percentY = (obj.top / this.canvas.height * 100).toFixed(2)
						obj.formData.x = this.form.widget.x
						obj.formData.y = this.form.widget.y
						obj.formData.percentX = this.form.widget.percentX
						obj.formData.percentY = this.form.widget.percentY
					}, 0)
				})
				// 缩放事件
				this.canvas.on('object:scaling', (e) => {
					var obj = e.target
					obj.setCoords()
					var label = obj._objects[1]
					var boundingRect = obj.getBoundingRect()
					var left = parseInt(boundingRect.left)
					var top = parseInt(boundingRect.top)
					var width = parseInt(boundingRect.width)
					var height = parseInt(boundingRect.height)
					// 限制缩放范围
					if (width + left > this.canvas.width ||
						height + top > this.canvas.height ||
						left < 0 ||
						top < 0 ||
						width < 1 ||
						height < 1) {
						obj.left = obj._stateProperties.left
						obj.top = obj._stateProperties.top
						obj.scaleX = obj._stateProperties.scaleX
						obj.scaleY = obj._stateProperties.scaleY
						obj.setCoords()
					} else {
						// 缩放时对文本进行反向缩放
						label.scaleX = 1 / (obj.scaleX)
						label.scaleY = 1 / (obj.scaleY)
						obj.saveState()
					}
					// 异步更新数据
					setTimeout(() => {
						this.form.widget.x = parseInt(obj.left)
						this.form.widget.percentX = (obj.left / this.canvas.width * 100).toFixed(2)
						this.form.widget.y = parseInt(obj.top)
						this.form.widget.percentY = (obj.top / this.canvas.height * 100).toFixed(2)
						this.form.widget.width = parseInt(obj.getScaledWidth().toFixed(2))
						this.form.widget.height = parseInt(obj.getScaledHeight().toFixed(2))
						this.form.widget.percentWidth = (obj.getScaledWidth() / this.canvas.width * 100)
							.toFixed(2)
						this.form.widget.percentHeight = (obj.getScaledHeight() / this.canvas.height * 100)
							.toFixed(2)
						obj.formData.x = this.form.widget.x
						obj.formData.y = this.form.widget.y
						obj.formData.percentX = this.form.widget.percentX
						obj.formData.percentY = this.form.widget.percentY
						obj.formData.width = this.form.widget.width
						obj.formData.height = this.form.widget.height
						obj.formData.percentWidth = this.form.widget.percentWidth
						obj.formData.percentHeight = this.form.widget.percentHeight
					}, 0)
				})
				this.canvas.on('mouse:down', (e) => {
					// 右键且在元素上右键
					// e.button: 1:左键 2:中键 3:右键
					// 在画布上点击 e.target为null
					if (e.button === 3 && e.target) {
						var obj = e.target
						this.canvas.setActiveObject(obj)
						this.canvas.renderAll()
						this.$refs.rightMenu.left = e.e.clientX + 5
						this.$refs.rightMenu.top = e.e.clientY + 5
						this.showRightMenu = true
					} else {
						this.showRightMenu = false
					}
				})
			},
			cancelActiveObject(e) {
				if (e.target == this.$refs.canvasBox) {
					this.clearFormData()
					this.canvas.discardActiveObject()
					this.canvas.renderAll()
					this.showRightMenu = false
				}
			},
			onWidgetClick(item) {
				let widget = {}
				widget.type = item.type
				widget.index = this.widgetData[item.typeString].length
				widget.typeString = item.typeString
				this.widget.forEach(item => {
					if (item.type == widget.type) {
						widget.icon = item.icon
						widget.disableIcon = item.disableIcon
						widget.multiple = item.multiple
						// 联动视频图片
						if (widget.type == 55) {
							let length = this.widgetData[widget.typeString].length
							if (widget.multiple) {
								widget.name = item.name + (length <= 0 ? length : length - 1)
							} else {
								widget.name = item.name
							}
							widget.index = length <= 0 ? length : length - 1
						}
						// 普通添加
						else {
							let length = this.widgetData[widget.typeString].length
							if (widget.multiple) {
								widget.name = item.name + length
							} else {
								widget.name = item.name
							}
							widget.index = length
						}
					}
				})
				// 控件数量限制
				if (!widget.multiple && this.widgetData[widget.typeString].length > 0) {
					this.$message.warning('此类型的控件只允许放置1个')
					return
				}
				if (widget.type != 55) {
					switch (widget.type) {
						// 背景
						case 0:
							widget.width = 300
							widget.height = 300
							widget.backgroundColor = this.defaultBackgroundColor
							break
							// LOGO
						case 1:
							widget.width = 150
							widget.height = 150
							break
							// 图片
						case 2:
							widget.width = 300
							widget.height = 300
							break
							// 视频
						case 3:
							widget.width = 300
							widget.height = 300
							break
							// 字幕
						case 4:
							widget.width = 500
							widget.height = 100
							widget.fontSize = this.defaultFontSize
							widget.fontColor = this.defaultFontColor
							widget.backgroundColor = this.defaultBackgroundColor
							widget.textSpeed = this.defaultTextSpeed
							break
							// DTMB
						case 5:
							widget.width = 300
							widget.height = 300
							break
							// 流媒体
						case 6:
							widget.width = 300
							widget.height = 300
							break
							// 天气
						case 50:
							widget.width = 300
							widget.height = 100
							widget.fontSize = this.defaultFontSize
							widget.fontColor = this.defaultFontColor
							widget.backgroundColor = this.defaultBackgroundColor
							break
							// 日期
						case 51:
							widget.width = 300
							widget.height = 100
							widget.fontSize = this.defaultFontSize
							widget.fontColor = this.defaultFontColor
							widget.backgroundColor = this.defaultBackgroundColor
							break
							// 时间
						case 52:
							widget.width = 300
							widget.height = 100
							widget.fontSize = this.defaultFontSize
							widget.fontColor = this.defaultFontColor
							widget.backgroundColor = this.defaultBackgroundColor
							break
							// 网页
						case 53:
							widget.width = 300
							widget.height = 300
							break
							// 站点列表
						case 54:
							widget.width = 300
							widget.height = 300
							widget.fontSize = this.defaultFontSize
							widget.fontColor = this.defaultFontColor
							widget.backgroundColor = this.defaultBackgroundColor
							break
						default:
							break
					}
					// 宽高百分比
					widget.percentWidth = (widget.width / this.canvas.width * 100).toFixed(2)
					widget.percentHeight = (widget.height / this.canvas.height * 100).toFixed(2)
					// 控件初始位置水平垂直居中
					// widget.x = this.form.canvasWidth / 2 - widget.width / 2
					// widget.y = this.form.canvasHeight / 2 - widget.height / 2
					widget.x = 0
					widget.y = 0
					// 坐标百分比
					widget.percentX = (widget.x / this.canvas.width * 100).toFixed(2)
					widget.percentY = (widget.y / this.canvas.height * 100).toFixed(2)
					// 普通控件绘制
					this.drawWidget(widget)
				} else {
					this.drawVideoImageWidget(widget)
				}
			},
			getWidgetTypeString(type) {
				var typeString = 'Unknow'
				switch (parseInt(type)) {
					// 背景
					case 0:
						typeString = 'Background'
						break
						// LOGO
					case 1:
						typeString = 'Logo'
						break
						// 图片
					case 2:
						typeString = 'Image'
						break
						// 视频
					case 3:
						typeString = 'Video'
						break
						// 字幕
					case 4:
						typeString = 'Text'
						break
						// DTMB
					case 5:
						typeString = 'Dtmb'
						break
						// 流媒体
					case 6:
						typeString = 'LiveSource'
						break
						// 天气
					case 50:
						typeString = 'Weather'
						break
						// 日期
					case 51:
						typeString = 'Date'
						break
						// 时间
					case 52:
						typeString = 'Time'
						break
						// 网页
					case 53:
						typeString = 'Website'
						break
						// 站点列表
					case 54:
						typeString = 'List'
						break
						// 联动视频图片
					case 55:
						typeString = 'VideoImage'
						break
					default:
						break
				}
				return typeString
			},
			getWidgetColor(type, childrenType) {
				var color = 'rgba(223, 223, 223, 0.7)'
				switch (parseInt(type)) {
					// 背景
					case 0:
						color = 'rgba(255, 220, 83, 0.7)'
						break
						// LOGO
					case 1:
						color = 'rgba(255, 120, 120, 0.7)'
						break
						// 图片
					case 2:
						color = 'rgba(124, 245, 255, 0.7)'
						break
						// 视频
					case 3:
						color = 'rgba(85, 170, 0, 0.7)'
						break
						// 字幕
					case 4:
						color = 'rgba(79, 211, 151, 0.7)'
						break
						// DTMB
					case 5:
						color = 'rgba(83, 183, 244, 0.7)'
						break
						// 流媒体
					case 6:
						color = 'rgba(139, 114, 247, 0.7)'
						break
						// 天气
					case 50:
						color = 'rgba(112, 224, 255, 0.7)'
						break
						// 日期
					case 51:
						color = 'rgba(139, 114, 247, 0.7)'
						break
						// 时间
					case 52:
						color = 'rgba(100, 80, 247, 0.7)'
						break
						// 网页
					case 53:
						color = 'rgba(83, 183, 244, 0.7)'
						break
						// 站点列表
					case 54:
						color = 'rgba(249, 137, 80, 0.7)'
						break
						// 联动视频图片
					case 55:
						if (childrenType == 0) {
							color = 'rgba(85, 170, 0, 0.7)'
						} else if (childrenType == 1) {
							color = 'rgba(124, 245, 255, 0.7)'
						}
						break
					default:
						break
				}
				return color
			},
			getVideoImageChildrenTypeString(childrenType) {
				if (childrenType == 0) {
					return '视频'
				} else if (childrenType == 1) {
					return '图片'
				}
			},
			drawWidget(widget) {
				widget.color = this.getWidgetColor(widget.type)
				// 绘制控件
				const rect = new fabric.Rect({
					originX: 'center',
					originY: 'center',
					width: widget.width,
					height: widget.height,
					fill: widget.color,
					strokeWidth: 0
				})
				const label = new fabric.IText(widget.name, {
					originX: 'center',
					originY: 'center',
					fill: 'rgba(255, 255, 255, 0.75)',
					shadow: new fabric.Shadow({
						color: 'rgba(0, 0, 0, 0.6)',
						blur: 1,
						offsetX: 2,
						offsetY: 2
					}),
					fontSize: 36
				})
				const rectWithLabel = new fabric.Group([rect, label], {
					left: widget.x,
					top: widget.y,
					width: widget.width,
					height: widget.height,
					noScaleCache: false
				})
				// 关闭旋转点
				rectWithLabel.setControlsVisibility({
					mtr: false
				})
				// 禁止负值翻转变换
				rectWithLabel.lockScalingFlip = true
				// 初始化控件基本属性
				rectWithLabel.formData = widget
				// 绑定事件
				rectWithLabel.on('selected', (e) => {
					var obj = e.target
					this.showWidgetStylePanel = false
					this.showBackgroundStylePanel = false
					this.showTextStylePanel = false
					this.showTextSpeedPanel = false
					this.showVideoImagePanel = false
					if (obj.formData.type == 0) {
						this.showWidgetStylePanel = true
						this.showBackgroundStylePanel = true
					} else if (obj.formData.type == 4) {
						this.showWidgetStylePanel = true
						this.showTextStylePanel = true
						this.showBackgroundStylePanel = true
						this.showTextSpeedPanel = true
					} else if (obj.formData.type == 50 || obj.formData.type == 51 || obj.formData.type == 52 || obj.formData.type == 54) {
						this.showWidgetStylePanel = true
						this.showTextStylePanel = true
						this.showBackgroundStylePanel = true
					}
					// 异步显示对象数据
					setTimeout(() => {
						this.form.widget.index = obj.formData.index
						this.form.widget.name = obj.formData.name
						this.form.widget.zIndex = obj.formData.zIndex
						this.form.widget.x = parseInt(obj.left)
						this.form.widget.y = parseInt(obj.top)
						this.form.widget.width = parseInt(obj.getScaledWidth().toFixed(2))
						this.form.widget.height = parseInt(obj.getScaledHeight().toFixed(2))
						this.form.widget.percentX = (obj.left / this.canvas.width * 100).toFixed(2)
						this.form.widget.percentY = (obj.top / this.canvas.height * 100).toFixed(2)
						this.form.widget.percentWidth = (obj.getScaledWidth().toFixed(2) / this.canvas
							.width * 100).toFixed(2)
						this.form.widget.percentHeight = (obj.getScaledHeight().toFixed(2) / this.canvas
							.height * 100).toFixed(2)
						this.form.widget.fontSize = obj.formData.fontSize
						this.form.widget.fontColor = obj.formData.fontColor ? obj.formData.fontColor : this
							.defaultFontColor
						this.form.widget.backgroundColor = obj.formData.backgroundColor ? obj.formData
							.backgroundColor : this.defaultBackgroundColor
						this.form.widget.textSpeed = obj.formData.textSpeed
					}, 100)
				})
				rectWithLabel.on('deselected', () => {
					this.clearFormData()
				})
				this.canvas.add(rectWithLabel)
				// this.canvas.setActiveObject(rectWithLabel)
				this.canvas.renderAll()
				rectWithLabel.saveState()
				this.canvas.getObjects().forEach((item, index) => item.formData.zIndex = index)
				// 保存数据
				this.widgetData[widget.typeString].push(widget)
			},
			drawVideoImageWidget(widget) {
				widget.width = 300
				widget.height = 300
				let video = cloneDeep(widget)
				let image = cloneDeep(widget)
				video.childrenType = 0
				// 宽高百分比
				video.percentWidth = (video.width / this.canvas.width * 100).toFixed(2)
				video.percentHeight = (video.height / this.canvas.height * 100).toFixed(2)
				// 控件初始位置
				// video.x = this.form.canvasWidth / 2 - video.width / 2 - video.width / 2 - 1
				// video.y = this.form.canvasHeight / 2 - video.height / 2
				video.x = 0
				video.y = 0
				// 坐标百分比
				video.percentX = (video.x / this.canvas.width * 100).toFixed(2)
				video.percentY = (video.y / this.canvas.height * 100).toFixed(2)
				this.drawVideoWidget(video)
				image.childrenType = 1
				// 宽高百分比
				image.percentWidth = (image.width / this.canvas.width * 100).toFixed(2)
				image.percentHeight = (image.height / this.canvas.height * 100).toFixed(2)
				// 控件初始位置
				image.x = this.form.canvasWidth / 2 - image.width / 2 + image.width / 2 + 1
				image.y = this.form.canvasHeight / 2 - image.height / 2
				image.x = 0
				image.y = widget.height + 1
				// 坐标百分比
				image.percentX = (image.x / this.canvas.width * 100).toFixed(2)
				image.percentY = (image.y / this.canvas.height * 100).toFixed(2)
				this.drawImageWidget(image)
			},
			drawVideoWidget(widget) {
				widget.color = this.getWidgetColor(widget.type, widget.childrenType)
				// 绘制控件
				const rect = new fabric.Rect({
					originX: 'center',
					originY: 'center',
					width: widget.width,
					height: widget.height,
					fill: widget.color,
					strokeWidth: 0
				})
				const label = new fabric.IText(widget.name, {
					originX: 'center',
					originY: 'center',
					fill: 'rgba(255, 255, 255, 0.75)',
					shadow: new fabric.Shadow({
						color: 'rgba(0, 0, 0, 0.6)',
						blur: 1,
						offsetX: 2,
						offsetY: 2
					}),
					fontSize: 36
				})
				const rectWithLabel = new fabric.Group([rect, label], {
					left: widget.x,
					top: widget.y,
					width: widget.width,
					height: widget.height,
					noScaleCache: false
				})
				// 关闭旋转点
				rectWithLabel.setControlsVisibility({
					mtr: false
				})
				// 禁止负值翻转变换
				rectWithLabel.lockScalingFlip = true
				// 初始化控件基本属性
				rectWithLabel.formData = widget
				// 绑定事件
				rectWithLabel.on('selected', (e) => {
					var obj = e.target
					this.showWidgetStylePanel = false
					this.showBackgroundStylePanel = false
					this.showTextStylePanel = false
					this.showTextSpeedPanel = false
					this.showVideoImagePanel = true
					// 异步显示对象数据
					setTimeout(() => {
						this.form.widget.index = obj.formData.index
						this.form.widget.name = obj.formData.name
						this.form.widget.zIndex = obj.formData.zIndex
						this.form.widget.childrenType = this.getVideoImageChildrenTypeString(obj.formData
							.childrenType)
						this.form.widget.x = parseInt(obj.left)
						this.form.widget.y = parseInt(obj.top)
						this.form.widget.width = parseInt(obj.getScaledWidth().toFixed(2))
						this.form.widget.height = parseInt(obj.getScaledHeight().toFixed(2))
						this.form.widget.percentX = (obj.left / this.canvas.width * 100).toFixed(2)
						this.form.widget.percentY = (obj.top / this.canvas.height * 100).toFixed(2)
						this.form.widget.percentWidth = (obj.getScaledWidth().toFixed(2) / this.canvas
							.width * 100).toFixed(2)
						this.form.widget.percentHeight = (obj.getScaledHeight().toFixed(2) / this.canvas
							.height * 100).toFixed(2)
					}, 100)
				})
				rectWithLabel.on('deselected', () => {
					this.clearFormData()
				})
				this.canvas.add(rectWithLabel)
				this.canvas.renderAll()
				rectWithLabel.saveState()
				this.canvas.getObjects().forEach((item, index) => item.formData.zIndex = index)
				// 保存数据
				this.widgetData[widget.typeString].push(widget)
			},
			drawImageWidget(widget) {
				widget.color = this.getWidgetColor(widget.type, widget.childrenType)
				// 绘制控件
				const rect = new fabric.Rect({
					originX: 'center',
					originY: 'center',
					width: widget.width,
					height: widget.height,
					fill: widget.color,
					strokeWidth: 0
				})
				const label = new fabric.IText(widget.name, {
					originX: 'center',
					originY: 'center',
					fill: 'rgba(255, 255, 255, 0.75)',
					shadow: new fabric.Shadow({
						color: 'rgba(0, 0, 0, 0.6)',
						blur: 1,
						offsetX: 2,
						offsetY: 2
					}),
					fontSize: 36
				})
				const rectWithLabel = new fabric.Group([rect, label], {
					left: widget.x,
					top: widget.y,
					width: widget.width,
					height: widget.height,
					noScaleCache: false
				})
				// 关闭旋转点
				rectWithLabel.setControlsVisibility({
					mtr: false
				})
				// 禁止负值翻转变换
				rectWithLabel.lockScalingFlip = true
				// 初始化控件基本属性
				rectWithLabel.formData = widget
				// 绑定事件
				rectWithLabel.on('selected', (e) => {
					var obj = e.target
					this.showWidgetStylePanel = false
					this.showBackgroundStylePanel = false
					this.showTextStylePanel = false
					this.showTextSpeedPanel = false
					this.showVideoImagePanel = true
					// 异步显示对象数据
					setTimeout(() => {
						this.form.widget.index = obj.formData.index
						this.form.widget.name = obj.formData.name
						this.form.widget.zIndex = obj.formData.zIndex
						this.form.widget.childrenType = this.getVideoImageChildrenTypeString(obj.formData
							.childrenType)
						this.form.widget.x = parseInt(obj.left)
						this.form.widget.y = parseInt(obj.top)
						this.form.widget.width = parseInt(obj.getScaledWidth().toFixed(2))
						this.form.widget.height = parseInt(obj.getScaledHeight().toFixed(2))
						this.form.widget.percentX = (obj.left / this.canvas.width * 100).toFixed(2)
						this.form.widget.percentY = (obj.top / this.canvas.height * 100).toFixed(2)
						this.form.widget.percentWidth = (obj.getScaledWidth().toFixed(2) / this.canvas
							.width * 100).toFixed(2)
						this.form.widget.percentHeight = (obj.getScaledHeight().toFixed(2) / this.canvas
							.height * 100).toFixed(2)
					}, 100)
				})
				rectWithLabel.on('deselected', () => {
					this.clearFormData()
				})
				this.canvas.add(rectWithLabel)
				this.canvas.renderAll()
				rectWithLabel.saveState()
				this.canvas.getObjects().forEach((item, index) => item.formData.zIndex = index)
				// 保存数据
				this.widgetData[widget.typeString].push(widget)
			},
			onWidgetNameChange(e) {
				var val = e.target.value
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val) {
					this.form.widget.name = obj._objects[1].text
					this.$message.warning('控件名称不能为空')
					return
				}
				// 联动视频图片
				if (obj.formData.type == 55) {
					obj.formData.name = val
					obj._objects[1].text = val
					let index = obj.formData.index
					this.canvas.getObjects().forEach(item => {
						if (item.formData.type == 55 && item.formData.index == index) {
							item.formData.name = val
							item._objects[1].text = val
						}
					})
					// 关联修改
				} else {
					obj.formData.name = val
					obj._objects[1].text = val
				}
				this.canvas.renderAll()
			},
			onWidgetXChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val && val != '0') {
					this.form.widget.x = obj.left
					this.$message.warning('x坐标不能为空')
					return
				}
				if (typeof(val) !== 'number') {
					this.form.widget.x = obj.left
					this.$message.warning('x坐标不正确')
					return
				}
				if (val < 0 || val > this.canvas.width - parseInt(obj.getScaledWidth().toFixed(2))) {
					this.form.widget.x = obj.left
					this.$message.warning('x坐标超出画布范围')
					return
				}
				obj.left = val
				obj.formData.x = val
				obj.formData.percentX = (val / this.canvas.width * 100).toFixed(2)
				this.form.widget.percentX = obj.formData.percentX
				obj.setCoords()
				this.canvas.renderAll()
			},
			onWidgetPercentXChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				var cacheObjLeft = parseInt(val * this.canvas.width / 100)
				if (!val && val != '0') {
					this.form.widget.percentX = obj.formData.percentX
					this.$message.warning('x坐标不能为空')
					return
				}
				if (typeof(val) !== 'number') {
					this.form.widget.percentX = obj.formData.percentX
					this.$message.warning('x坐标不正确')
					return
				}

				if (cacheObjLeft < 0 || cacheObjLeft > this.canvas.width - parseInt(obj.getScaledWidth().toFixed(2))) {
					this.form.widget.percentX = obj.formData.percentX
					this.$message.warning('x坐标超出画布范围')
					return
				}
				obj.setCoords()
				obj.left = cacheObjLeft
				obj.formData.percentX = val
				obj.formData.x = cacheObjLeft
				this.form.widget.x = obj.formData.x
				obj.setCoords()
				this.canvas.renderAll()
			},
			onWidgetYChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val && val != '0') {
					this.form.widget.y = obj.top
					this.$message.warning('y坐标不能为空')
					return
				}
				if (typeof(val) !== 'number') {
					this.form.widget.y = obj.top
					this.$message.warning('y坐标不正确')
					return
				}
				if (val < 0 || val > this.canvas.height - parseInt(obj.getScaledHeight().toFixed(2))) {
					this.form.widget.y = obj.top
					this.$message.warning('y坐标超出画布范围')
					return
				}
				obj.setCoords()
				obj.top = val
				obj.formData.y = val
				obj.formData.percentY = (val / this.canvas.height * 100).toFixed(2)
				this.form.widget.percentY = obj.formData.percentY
				obj.setCoords()
				this.canvas.renderAll()
			},
			onWidgetPercentYChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				var cacheObjTop = parseInt(val * this.canvas.height / 100)
				if (!val && val != '0') {
					this.form.widget.percentY = obj.formData.percentY
					this.$message.warning('y坐标不能为空')
					return
				}
				if (typeof(val) !== 'number') {
					this.form.widget.percentY = obj.formData.percentY
					this.$message.warning('y坐标不正确')
					return
				}
				if (cacheObjTop < 0 || cacheObjTop > this.canvas.height - parseInt(obj.getScaledHeight().toFixed(2))) {
					this.form.widget.percentY = obj.formData.percentY
					this.$message.warning('y坐标超出画布范围')
					return
				}
				obj.setCoords()
				obj.top = cacheObjTop
				obj.formData.percentY = val
				obj.formData.y = cacheObjTop
				this.form.widget.y = obj.formData.y
				obj.setCoords()
				this.canvas.renderAll()
			},
			onWidgetWidthChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val && val != '0') {
					this.form.widget.width = obj.formData.width
					this.$message.warning('宽度不能为空')
					return
				}
				if (typeof(val) !== 'number') {
					this.form.widget.width = obj.formData.width
					this.$message.warning('宽度不正确')
					return
				}
				if (val < 1) {
					this.form.widget.width = obj.formData.width
					this.$message.warning('宽度不能小于1')
					return
				}
				if (val > this.canvas.width - obj.left) {
					this.form.widget.width = obj.formData.width
					this.$message.warning('宽度超出画布范围')
					return
				}
				obj.setCoords()
				obj.scaleX = obj.scaleX * val / (parseInt(obj.getScaledWidth().toFixed(2)))
				var label = obj._objects[1]
				label.scaleX = 1 / (obj.scaleX)
				label.scaleY = 1 / (obj.scaleY)
				obj.formData.width = val
				obj.formData.percentWidth = (val / this.canvas.width * 100).toFixed(2)
				obj.formData.x = parseInt(obj.left)
				obj.formData.percentX = (obj.left / this.canvas.width * 100).toFixed(2)
				this.form.widget.x = obj.formData.x
				this.form.widget.percentX = obj.formData.percentX
				this.form.widget.percentWidth = obj.formData.percentWidth
				obj.saveState()
				obj.setCoords()
				this.canvas.renderAll()
			},
			onWidgetPercentWidthChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				var cacheObjWidth = parseInt(val * this.canvas.width / 100)
				if (!val && val != '0') {
					this.form.widget.percentWidth = obj.formData.percentWidth
					this.$message.warning('宽度不能为空')
					return
				}
				if (typeof(val) !== 'number') {
					this.form.widget.percentWidth = obj.formData.percentWidth
					this.$message.warning('宽度不正确')
					return
				}
				if (cacheObjWidth < 1) {
					this.form.widget.percentWidth = obj.formData.percentWidth
					this.$message.warning('宽度不能小于1')
					return
				}
				if (cacheObjWidth > this.canvas.width - obj.left) {
					this.form.widget.percentWidth = obj.formData.percentWidth
					this.$message.warning('宽度超出画布范围')
					return
				}
				obj.setCoords()
				obj.scaleX = obj.scaleX * cacheObjWidth / (parseInt(obj.getScaledWidth().toFixed(2)))
				var label = obj._objects[1]
				label.scaleX = 1 / (obj.scaleX)
				label.scaleY = 1 / (obj.scaleY)
				obj.formData.percentWidth = val
				obj.formData.width = cacheObjWidth
				obj.formData.x = parseInt(obj.left)
				obj.formData.percentX = (obj.left / this.canvas.width * 100).toFixed(2)
				this.form.widget.x = obj.formData.x
				this.form.widget.percentX = obj.formData.percentX
				this.form.widget.width = obj.formData.width
				obj.saveState()
				obj.setCoords()
				this.canvas.renderAll()
			},
			onWidgetHeightChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val && val != '0') {
					this.form.widget.height = obj._stateProperties.height
					this.$message.warning('高度不能为空')
					return
				}
				if (typeof(val) !== 'number') {
					this.form.widget.height = obj._stateProperties.height
					this.$message.warning('高度不正确')
					return
				}
				if (val < 1) {
					this.form.widget.height = obj._stateProperties.height
					this.$message.warning('高度不能小于1')
					return
				}
				if (val > this.canvas.height - obj.top) {
					this.form.widget.height = obj._stateProperties.height
					this.$message.warning('高度超出画布范围')
					return
				}
				obj.setCoords()
				obj.scaleY = obj.scaleY * val / (parseInt(obj.getScaledHeight().toFixed(2)))
				var label = obj._objects[1]
				label.scaleX = 1 / (obj.scaleX)
				label.scaleY = 1 / (obj.scaleY)
				obj.formData.height = val
				obj.formData.percentHeight = (val / this.canvas.height * 100).toFixed(2)
				obj.formData.y = parseInt(obj.top)
				obj.formData.percentY = (obj.top / this.canvas.height * 100).toFixed(2)
				this.form.widget.y = obj.formData.y
				this.form.widget.percentY = obj.formData.percentY
				this.form.widget.percentHeight = obj.formData.percentHeight
				obj.saveState()
				obj.setCoords()
				this.canvas.renderAll()
			},
			onWidgetPercentHeightChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				var cacheObjHeight = parseInt(val * this.canvas.height / 100)
				if (!val && val != '0') {
					this.form.widget.percentHeight = obj.formData.percentHeight
					this.$message.warning('高度不能为空')
					return
				}
				if (typeof(val) !== 'number') {
					this.form.widget.percentHeight = obj.formData.percentHeight
					this.$message.warning('高度不正确')
					return
				}
				if (cacheObjHeight < 1) {
					this.form.widget.percentHeight = obj.formData.percentHeight
					this.$message.warning('高度不能小于1')
					return
				}
				if (cacheObjHeight <= 0 || cacheObjHeight > this.canvas.height - obj.top) {
					this.form.widget.percentHeight = obj.formData.percentHeight
					this.$message.warning('高度超出画布范围')
					return
				}
				obj.setCoords()
				obj.scaleY = obj.scaleY * cacheObjHeight / (parseInt(obj.getScaledHeight().toFixed(2)))
				var label = obj._objects[1]
				label.scaleX = 1 / (obj.scaleX)
				label.scaleY = 1 / (obj.scaleY)
				obj.formData.percentHeight = val
				obj.formData.height = cacheObjHeight
				obj.formData.y = parseInt(obj.top)
				obj.formData.percentY = (obj.top / this.canvas.height * 100).toFixed(2)
				this.form.widget.y = obj.formData.y
				this.form.widget.percentY = obj.formData.percentY
				this.form.widget.height = obj.formData.height
				obj.saveState()
				obj.setCoords()
				this.canvas.renderAll()
			},
			onWidgetFontSizeChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val) {
					this.form.widget.fontSize = obj.formData.fontSize
					this.$message.warning('字体大小不能为空')
					return
				}
				obj.formData.fontSize = val
			},
			onColorPickerWidgetFontColorChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val) {
					this.form.widget.fontColor = obj.formData.fontColor
					this.$message.warning('字体颜色不能为空')
					return
				}
				obj.formData.fontColor = val
				this.form.widget.fontColor = obj.formData.fontColor
			},
			onWidgetFontColorChange(e) {
				var val = e.target.value
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val) {
					this.form.widget.fontColor = obj.formData.fontColor
					this.$message.warning('字体颜色不能为空')
					return
				}
				obj.formData.fontColor = val
				this.form.widget.fontColor = obj.formData.fontColor
			},
			onColorPickerWidgetBackgroundColorChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val) {
					this.form.widget.backgroundColor = obj.formData.backgroundColor
					this.$message.warning('背景颜色不能为空')
					return
				}
				obj.formData.backgroundColor = val
				this.form.widget.backgroundColor = obj.formData.backgroundColor
			},
			onWidgetBackgroundColorChange(e) {
				var val = e.target.value
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val) {
					this.form.widget.backgroundColor = obj.formData.backgroundColor
					this.$message.warning('背景颜色不能为空')
					return
				}
				obj.formData.backgroundColor = val
				this.form.widget.backgroundColor = obj.formData.backgroundColor
			},
			onWidgetTextSpeedChange(val) {
				var obj = this.canvas.getActiveObject()
				if (!obj) {
					return
				}
				if (!val) {
					this.form.widget.textSpeed = obj.formData.textSpeed
					this.$message.warning('字幕速度不能为空')
					return
				}
				obj.formData.textSpeed = val
			},
			saveCanvasToJSON() {
				let widgets = this.canvas.toObject(['formData']).objects.map(item => item.formData)
				let data = {
					organizationId: this.form.organizationId,
					name: this.form.name,
					type: this.form.type,
					remarks: this.form.remarks,
					width: this.form.canvasWidth,
					height: this.form.canvasHeight,
					widgets: widgets
				}
				return data
			},
			exportCanvasToImage() {
				const base64 = this.canvas.toDataURL({
					width: this.canvas.width,
					height: this.canvas.height,
					left: 0,
					top: 0,
					format: 'png'
				})
				return base64ToFile(base64, this.form.name + '.png')
			},
			queryOrganizationTreeAction() {
			},
			submitCheck() {
				var canSubmit = false
				this.$refs.form.validate((valid) => {
					if (valid) {
						if (!this.canvas.getObjects() || this.canvas.getObjects().length <= 0) {
							this.$message.warning('请添加控件')
							canSubmit = false
						} else {
							canSubmit = true
						}
					}
				})
				return canSubmit
			},
			redrawCanvas(data) {
				this.form.organizationId = data.organizationId
				this.form.name = data.name
				this.form.type = data.type
				this.form.remarks = data.remarks
				this.form.canvasWidth = data.width
				this.form.canvasHeight = data.height
				// 加载模版控件数据
				var widgets = data.widgets
				widgets.forEach(item => {
					let widgetType = item.type
					item.typeString = this.getWidgetTypeString(widgetType)
					// 联动视频图片
					if (widgetType == 55) {
						let childrenType = item.childrenType
						if (childrenType == 0) {
							this.drawVideoWidget(item)
						} else if (childrenType == 1) {
							this.drawImageWidget(item)
						}
					}
					// 普通添加
					else {
						this.drawWidget(item)
					}
				})
				this.clearFormData()
				this.canvas.discardActiveObject()
				this.canvas.renderAll()
				this.showRightMenu = false
			}
		},
		mounted() {
			this.getDict(JSON.stringify({
				code: 'TEMPLATE_TYPE'
			})).then(res => this.dict.type = res.data.data)
			this.queryOrganizationTreeAction()
			this.initCanvas()
		}
	}
</script>
<style scoped lang="less">
	/deep/.ant-card {
		border: 1px solid #d9d9d9;
	}

	/deep/.ant-card-head {
		background-color: #fafafa;
		margin-bottom: 0px;
		border-bottom: 1px solid #d9d9d9;
	}

	/deep/.ant-card-head-title {
		padding: 12px 0px;
		font-size: 14px;
	}

	/deep/.ant-card-bordered {
		border-radius: 4px;
	}

	/deep/.ant-list-item:hover {
		background-color: #f0f0f0;
		cursor: pointer;
	}

	/deep/.ant-collapse-content>.ant-collapse-content-box {
		padding: 8px;
	}

	/deep/.ant-form-item {
		margin-bottom: 4px;
	}

	.widget-card {
		padding-right: 12px;
		height: calc(100vh - 102px) !important;
		overflow-y: auto;
	}

	.canvas-context {
		border: 1px solid #d9d9d9;
		border-radius: 4px;
		overflow: auto;
		background: #f4f4f4;
		background-image:
			linear-gradient(rgba(250, 250, 250, 0.5) 1px, transparent 0),
			linear-gradient(90deg, rgba(250, 250, 250, 0.5) 1px, transparent 0),
			linear-gradient(white 2px, transparent 0),
			linear-gradient(90deg, white 2px, transparent 0);
		background-size: 15px 15px, 15px 15px, 75px 75px, 75px 75px;
	}

	.canvas-box {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 100%;
		height: calc(100vh - 102px) !important;
	}

	/deep/.m-colorPicker {
		display: block;
	}

	/deep/.m-colorPicker .box {
		z-index: 3;
	}

	/deep/.m-colorPicker .colorBtn {
		width: 30px;
		height: 30px;
		border-radius: 2px;
	}
</style>
